home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Ken Long / NewMaxwell-c / Original / phys.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-04  |  4.1 KB  |  183 lines  |  [TEXT/KAHL]

  1. /*
  2.  * do collisions and movement
  3.  */
  4.  
  5. #include "ball.h"
  6.  
  7. extern wide, tall;            /* the size of the box we are in */
  8. extern GateState;            /* != 0 iff gate is open */
  9.  
  10. #define TWO(X) ((X)+(X))
  11. #define THREE(X) (TWO(X)+(X))
  12.  
  13. /*
  14.  * bbump() deals with a possible collision between two specific balls.
  15.  * The first ball will not be to the right of the second ball.  Returns
  16.  * one if the second ball is far enough to the right so that no balls
  17.  * farther right could collide with the first ball, else returns zero
  18.  */
  19. bbump( pA, pB )
  20.     register ball *pA, *pB;
  21. {
  22.     register long k;
  23.     long tAvx, tAvy;
  24.     register long tBx, tBy;
  25.     long tBvx, tBvy;
  26.     long WIDE, TALL;
  27.     
  28.     WIDE = wide<<2;            /* scale from window to physical co-ords */
  29.     TALL = tall<<2;
  30.     
  31.     /*
  32.      * Deal with the barrier and the gate
  33.      */
  34.     if ( TWO(pA->x) <= WIDE && TWO(pB->x) >= WIDE )
  35.         /* gate closed means no collision */
  36.         if ( ! GateState )
  37.             return 0;
  38.         else
  39.         /* if either ball is below gate, no collision */
  40.         if ( THREE(pA->y) < TALL || THREE(pB->y) < TALL )
  41.             return 0;
  42.         else
  43.         /* if either ball is above gate, no collision */
  44.         if ( THREE(pA->y) > TWO(TALL) || THREE(pB->y) > TWO(TALL) )
  45.             return 0;
  46.  
  47.     /* shift to A's co-ordinate system */
  48.     tBx = pB->x - pA->x;
  49.     tBy = pB->y - pA->y;
  50.     tBvx = pB->vx - pA->vx;    tAvx = 0;
  51.     tBvy = pB->vy - pA->vy;    tAvy = 0;
  52.     
  53.     /*
  54.      * see if the balls are close enough to have collided
  55.      */
  56.     if ( tBx > TWO(CRAD) )
  57.         return 1;
  58.     if ( tBx * tBx + tBy * tBy > (CRAD*CRAD<<2) )
  59.         return 0;
  60.     
  61.     k = tBx * tBvx + tBy * tBvy;
  62.     
  63.     /*
  64.      * make sure they are going towards each other
  65.      */    
  66.     if ( k > -1 )
  67.         return 0;
  68.         
  69.     k = ( tBy * tBvx - tBx * tBvy ) / k;
  70.     
  71.     tAvx = ( tBvx - k * tBvy ) / ( 1 + k*k );
  72.     tAvy = ( k * tBvx + tBvy ) / ( 1 + k*k );
  73.     
  74.     tBvx =  k * tAvy;
  75.     tBvy = -k * tAvx;
  76.     
  77.     pB->vx = pA->vx + tBvx;
  78.     pB->vy = pA->vy + tBvy;
  79.     pA->vx += tAvx;
  80.     pA->vy += tAvy;
  81.     
  82.     return 0;
  83. }
  84.  
  85. /*
  86.  * Because the calculations above use longs instead of floats, we have a
  87.  * lot of round off error.  This seems to manifest itself by causing the
  88.  * balls to slow down over time.  We use the walls to correct this.
  89.  *
  90.  * If "we" is greater than zero, we are attempting to add energy to the
  91.  * system.  We do this by looking for slow balls bouncing off the right
  92.  * wall.  When we find such a ball, we give it a swift kick towards the
  93.  * left.
  94.  *
  95.  * If "we" is less than zero, then we are trying to remove energt from
  96.  * the system for some reason.  In this case, the outer walls become
  97.  * slightly sticky, with the ball slowing down by abs(we) perpendicular
  98.  * to the wall.
  99.  *
  100.  * This stuff is done in wbump().
  101.  *
  102.  */
  103.  
  104. static int we = 0;            /* wall energy factor */
  105.  
  106. walls( i ) {
  107.     we = i;
  108. }
  109.  
  110. /*
  111.  * wump() checks for collisions between a ball walls or the gate
  112.  */
  113. wbump( pA )
  114.     register ball *pA;
  115. {
  116.     register long WIDE, TALL;
  117.     
  118.     WIDE = wide<<2; TALL = tall<<2;
  119.     
  120.     if ( (pA->x <= CRAD && pA->vx < 0)
  121.       || (pA->x >= WIDE-CRAD && pA->vx > 0) ) {
  122.         pA->vx = -pA->vx;
  123.         if ( we > 0 ) {
  124.             if ( pA->vx < 0 && pA->pict == 0 && pA->x >= WIDE-CRAD)
  125.                 pA->vx -= 30;                /* swift kick */
  126.         } else {
  127.             if ( pA->vx > 0 )
  128.                 pA->vx += we;
  129.             else
  130.                 pA->vx -= we;
  131.         }
  132.     }
  133.     if ( (pA->y <= CRAD && pA->vy < 0)
  134.       || (pA->y >= TALL-CRAD && pA->vy > 0) ) {
  135.         pA->vy = -pA->vy;
  136.         if ( we < 0 ) {
  137.             if ( pA->vy > 0 )
  138.                 pA->vy += we;
  139.             else
  140.                 pA->vy -= we;
  141.         }
  142.  
  143.     }
  144.     
  145.     /*
  146.      * if the ball is on the same level as the gate, and the gate is open,
  147.      * there is nothing for the ball to hit on the barrier
  148.      */
  149.     if ( TALL < THREE(pA->y) && THREE(pA->y) < TWO(TALL) && GateState )
  150.         return;
  151.         
  152.     WIDE >>= 1;            /* location of the barrier */
  153.  
  154.     /*
  155.      * see if the ball hits the barrier
  156.      */
  157.     if ( pA->x <= WIDE && pA->vx > 0 ) {
  158.         if ( pA->x + CRAD >= WIDE || pA->x + pA->vx > WIDE )
  159.             pA->vx = -pA->vx;
  160.     } else
  161.     if ( pA->x >= WIDE &&  pA->vx < 0 )
  162.         if ( pA->x - CRAD <= WIDE || pA->x + pA->vx < WIDE )
  163.             pA->vx = -pA->vx;
  164. }
  165.  
  166. mball( pA )
  167.     ball *pA;
  168. {
  169.     register long vx, vy;
  170.     pA->x += vx = pA->vx;
  171.     pA->y += vy = pA->vy;
  172.  
  173.     /*
  174.      * check for stalled balls, and offer them a chance to get going again
  175.      */
  176.     if ( vx == 0 && vy == 0 ) {
  177.         if ( Random() > 0 )
  178.             pA->vx = Random() > 0 ? 1 : -1;
  179.         if ( Random() > 0 )
  180.             pA->vy = Random() > 0 ? 1 : -1;
  181.     }
  182. }
  183.